package conservare.modelo.contrato;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import conservare.listener.AuditoriaListener;
import conservare.modelo.Auditavel;
import conservare.modelo.Auditoria;
import conservare.modelo.ItemDeDiaSemana;
import conservare.modelo.Pessoa;
import conservare.modelo.localservico.LocalPrestacaoServico;
import conservare.modelo.servico.ServicoComplementar;
import conservare.modelo.servico.ServicoPrincipal;
import conservare.modelo.type.DiaSemana;
import conservare.modelo.type.Periodicidade;
import conservare.modelo.type.SituacaoContrato;
import conservare.modelo.type.TipoServicoComplementar;

@Entity
@Table(name="TB_CONTRATO")
@EntityListeners(AuditoriaListener.class)
public class Contrato implements Auditavel, Serializable{
	
	private static final long serialVersionUID = 2402154082687331742L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="CONTRATO_ID")
	private Integer id;
	
	@ManyToOne(targetEntity=Pessoa.class)
	@JoinColumn(name="CONTRATANTE_ID")
	private Pessoa contratante;
	
	@OneToOne(mappedBy="contrato", cascade=CascadeType.ALL)
	private ServicoPrincipal servicoPrincipal;
	
	@OneToMany(mappedBy="contrato", cascade=CascadeType.ALL)
	private List<ServicoComplementar> servicosComplementares = new ArrayList<>();
	
	
	@ManyToOne
	@JoinColumn(name="LOCAL_PS_ID")
	private LocalPrestacaoServico localPrestacaoServico;
	
	@Column(name="vlr_contrato")
	private BigDecimal valorContrato = new BigDecimal(0.0);
	
	@Temporal(TemporalType.DATE)
	@Column(name="dt_inicio_vigencia")
	private Date dataInicioVigencia;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="dt_fim_vigencia")
	private Date dataFimVigencia;
	
	@Temporal(TemporalType.DATE)
	@Column(name="dt_cancelamento_contrato")
	private Date dataCancelamento;
	
	@Column(name="motivo_fim_contrato")
	private String motivoFimContrato;
	
	private String observacao;
	
	@Enumerated(EnumType.ORDINAL)
	private SituacaoContrato situacao = SituacaoContrato.EM_PROCESSO;
	
	private Auditoria auditoria;

	@Transient
	private Integer novaQtdHorasServicoLimpeza;
	
	
	public void adicionarContratante(Pessoa contratante){
		contratante.adicionaContrato(this);
		this.contratante = contratante;
	}
	
	public void adiconarLocalPrestacaoServico(LocalPrestacaoServico local){
		this.localPrestacaoServico = local;
	}
	
	public void adicionarServicoPrincipal(ServicoPrincipal servicoPrincipal){
		servicoPrincipal.setContrato(this);
		this.servicoPrincipal = servicoPrincipal;
	}
	
	public void adicionarServicoComplementar(ServicoComplementar servicoComplementar){
		servicoComplementar.setContrato(this);
		this.servicosComplementares.add(servicoComplementar);
	}
	
	public void adicionarResponsavelPeloLocalPrestacaoServico(Pessoa responsavelLocalPrestacaoServico){
		this.localPrestacaoServico.adicionarResponsavelPeloLocalPrestacaoServico(responsavelLocalPrestacaoServico);
	}
	
	public void adicionarDiaNaAgendaServicoPrincipal(DiaSemana diaSemana, Date qtdHorasDia){
		getServicoPrincipal().adicionarDiaSemanaNaAgenda(diaSemana, qtdHorasDia);
	}
	
	public void removerDiaNaAgendaServicoPrincipal(ItemDeDiaSemana itemDeDiaSemanaRemover){
		getServicoPrincipal().removerDiaSemanaDaAgenda(itemDeDiaSemanaRemover);
	}
	
	
	public void removerServicoComplementarDoContrato(ServicoComplementar servicoComplementar){
		if(getServicosComplementares().size() > 0){
			getServicosComplementares().remove(servicoComplementar);
		}
	}
	
	public void adicionarServicoComplementar(TipoServicoComplementar tipoServicoComplementar, Periodicidade periodicidade){
		
		if(isServicoComplementarExisteNoContrato(tipoServicoComplementar)){
			obterServicoComplementarDesteTipo(tipoServicoComplementar).setPeriodicidade(periodicidade);
		}else{
			ServicoComplementar servicoComplementar = new ServicoComplementar(this, tipoServicoComplementar, periodicidade);
			getServicosComplementares().add(servicoComplementar);
		}

	}
	
	public void removerDiaSemanaDaAgenda(ServicoComplementar servicoComplementar){
		
		if(getServicosComplementares().size() > 0){
			getServicosComplementares().remove(servicoComplementar);
		}
		
	}

	public boolean isServicoComplementarExisteNoContrato(TipoServicoComplementar tipoServicoComplementar){
		
		boolean servicoComplementarExisteNaLista = false;
		
		for(ServicoComplementar servicoComplementar : getServicosComplementares()){
			if(servicoComplementar.getTipoServicoComplementar() == tipoServicoComplementar){
				servicoComplementarExisteNaLista = true;
				break;
			}
		}
		
		return servicoComplementarExisteNaLista;
		
	}
	
	private ServicoComplementar obterServicoComplementarDesteTipo(TipoServicoComplementar tipoServicoComplementar){
		
		ServicoComplementar servicoComplementarLocalizado = null;
		
		for(ServicoComplementar servicoComplementar : getServicosComplementares()){
			if(servicoComplementar.getTipoServicoComplementar() == tipoServicoComplementar){
				servicoComplementarLocalizado = servicoComplementar;
				break;
			}
		}
		
		return servicoComplementarLocalizado;
	}
	
	
	
	
	
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	

	public BigDecimal getValorContrato() {
		return valorContrato;
	}
	public void setValorContrato(final BigDecimal valorContrato) {
		if(valorContrato == null)
			this.valorContrato = new BigDecimal(0.0);
		else
			this.valorContrato = valorContrato;
	}
	public Date getDataInicioVigencia() {
		return dataInicioVigencia;
	}
	public void setDataInicioVigencia(Date dataInicioVigencia) {
		this.dataInicioVigencia = dataInicioVigencia;
	}
	public Date getDataFimVigencia() {
		return dataFimVigencia;
	}
	public void setDataFimVigencia(Date dataFimVigencia) {
		this.dataFimVigencia = dataFimVigencia;
	}
	
	public Date getDataCancelamento() {
		return dataCancelamento;
	}

	public String getMotivoFimContrato() {
		return motivoFimContrato;
	}

	public void setMotivoFimContrato(String motivoFimContrato) {
		this.motivoFimContrato = motivoFimContrato;
	}

	public void setDataCancelamento(Date dataCancelamento) {
		this.dataCancelamento = dataCancelamento;
	}

	public String getObservacao() {
		return observacao;
	}
	public void setObservacao(String observacao) {
		this.observacao = observacao;
	}
	public SituacaoContrato getSituacao() {
		return situacao;
	}
	public void setSituacao(SituacaoContrato situacao) {
		this.situacao = situacao;
	}
	public Auditoria getAuditoria() {
		return auditoria;
	}
	public void setAuditoria(Auditoria auditoria) {
		this.auditoria = auditoria;
	}
	
	public Integer getNovaQtdHorasServicoLimpeza() {
		return novaQtdHorasServicoLimpeza;
	}

	public void setNovaQtdHorasServicoLimpeza(Integer novaQtdHorasServicoLimpeza) {
		this.novaQtdHorasServicoLimpeza = novaQtdHorasServicoLimpeza;
	}

	public Pessoa getContratante() {
		return contratante;
	}
	public void setContratante(Pessoa contratante) {
		this.contratante = contratante;
	}
	
	public LocalPrestacaoServico getLocalPrestacaoServico() {
		return localPrestacaoServico;
	}
	
	public void setLocalPrestacaoServico(LocalPrestacaoServico local) {
		this.localPrestacaoServico = local;
	}
	
	public ServicoPrincipal getServicoPrincipal() {
		return servicoPrincipal;
	}

	public List<ServicoComplementar> getServicosComplementares() {
		return servicosComplementares;
	}

	public Pessoa getResponsavelLocalPrestacaoServico(){
		return localPrestacaoServico != null ? localPrestacaoServico.getResponsavel() : null;
	}
	
	
	public boolean isEmProcesso(){
		return getSituacao()!= null && getSituacao() == SituacaoContrato.EM_PROCESSO;
	}
	
	public boolean isAtivo(){
		return getSituacao()!= null && getSituacao() == SituacaoContrato.ATIVO;
	}
	
	public boolean isDescontinuado(){
		return getSituacao()!= null && getSituacao() == SituacaoContrato.DESCONTINUADO;
	}
	
	public boolean isCancelado(){
		return getSituacao()!= null && getSituacao() == SituacaoContrato.CANCELADO;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Contrato other = (Contrato) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
	
}
